#include <avr/io.h>
#include <avr/iom164.h> 
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define CONTROL 	0x9F
#define CHARACTER	0xFE
//#include "WProgram.h"
//#include "SerialLCD.h"
//#include "NewSoftSerial.h"

void power_on ();
void get_data();
void serial_init();
void print_lcd(char data[]);
void lcd_transmit(unsigned char data);
unsigned char lcd_receive();
void lcd_flush();
void obd_transmit(unsigned char data);
unsigned char obd_receive();

char mask[] = {
	0b00000001,
	0b00000010,
	0b00000100,
	0b00001000,
	0b00010000,
	0b00100000,
	0b01000000,
	0b10000000};

int main(void){
	serial_init(); // Initialize Serial
	power_on(); // Turn Power Light On

	while(1){
		get_data();
	}		
} 

void power_on (){
	DDRA=0xff;
	DDRD=0xff;
	PORTA = 0x01;
}

void get_data (){
while(1){
	int h;
	/*for(h=0;h<255;h++){
		lcd_transmit(h);
	}
	while(1){
		PORTA = 0x04;
		int talk = lcd_receive();
		lcd_transmit(talk);
	}*/
/*	PORTA = 0x07;
	_delay_ms(4000);	
	int flag = 0;
	unsigned char data, data1;
	PORTA = 0x01;
	lcd_flush();
	data = lcd_receive();	
	PORTA = 0x07;
	PORTA = 0x02;
	if (data == 0xA3){
		lcd_flush();	
		lcd_transmit(0x9F);
		PORTA = 0x02;
		lcd_transmit(0x83);
		PORTA = 0x03;
		lcd_transmit(0xA5);
		PORTA = 0x04;
		data = lcd_receive();
		PORTA = 0x05;
		if (data == 0xAA){
			lcd_flush();
			// Turn on Backlight

			lcd_transmit(CONTROL);
			lcd_transmit(0x81);
		
			// LCD On

			lcd_transmit(CONTROL);
			lcd_transmit(0x83);

			// LCD Clear
			
			lcd_transmit(CONTROL);
			lcd_transmit(0x65);

			// Display On
	
		//	lcd_transmit(CONTROL);
		//	lcd_transmit(0x64);

			// Return Home

			lcd_transmit(CONTROL);
			lcd_transmit(0x61);
			
			// Cursor On

			lcd_transmit(CONTROL);
			lcd_transmit(0x67);

			// Blink On

	//		lcd_transmit(CONTROL);
	//		lcd_transmit(0x69);
			
		//	lcd_transmit(CONTROL);
		//	lcd_transmit(0x71);
	
			// Left to right

			lcd_transmit(CONTROL);
			lcd_transmit(0x70);

			// Autoscroll
			
	//		lcd_transmit(CONTROL);
	//		lcd_transmit(0x6D);

			//while(1){}
		//	lcd_transmit(CONTROL);
		//	lcd_transmit(0x6C);
			// Set cursor

		/*	lcd_transmit(CONTROL);
			lcd_transmit(0xFF);
			PORTA = 0x06;
			while( (data = lcd_receive()) != 0x5A);
			lcd_transmit(0x80);
			lcd_transmit(0x00);
						
			// Set cursor again

			lcd_transmit(CONTROL);
			lcd_transmit(0xFF);
			while( (data = lcd_receive()) != 0x5B);
			lcd_transmit(0x80);
			lcd_transmit(0x00);*/
			
			/*int j = 0;
			long i = 0;
			PORTA = 0x03;
			
			lcd_flush();
			lcd_transmit(CHARACTER);
			_delay_ms(20);
			lcd_flush();*/
			
			PORTA = 0x06;
			lcd_transmit('s');
			lcd_transmit('u');
			lcd_transmit('c');
			lcd_transmit('k');
			lcd_transmit(' ');
			lcd_transmit('i');
			lcd_transmit('t');
			lcd_transmit(' ');
			lcd_transmit('b');
			lcd_transmit('r');
			lcd_transmit('i');
			lcd_transmit('a');
			lcd_transmit('n');
			lcd_transmit(' ');
			lcd_transmit(CONTROL);
			//lcd_transmit(0x65);
			//lcd_transmit(CHARACTER);
			unsigned char x;
			//do{
			//	x = obd_receive();
			//	lcd_transmit(x);
			//}while(x!=0x3E);
			//lcd_transmit(CONTROL);
			//lcd_transmit(0x65);
			//lcd_transmit(CONTROL);
			//lcd_transmit(0x61);
			_delay_ms(2000);
			PORTA = 0x02;
			obd_transmit('A');
			//lcd_transmit(obd_receive());
			_delay_ms(20);
			obd_transmit('T');
			_delay_ms(20);
			//lcd_transmit(obd_receive());
			obd_transmit('Z');
			_delay_ms(20);
			//lcd_transmit(obd_receive());
			obd_transmit(0x0D);
			_delay_ms(20);
			//lcd_transmit(obd_receive());
			//lcd_transmit(CHARACTER);
			/*int m;
			int b;
			int tmp;
			int count = 0;
			char data2[30];
			do{
				data2[count] = obd_receive();
				if(data2[count] == 0x3E) flag = 1;
				count++;
			}while(flag != 1);
			lcd_transmit(CHARACTER);
			lcd_transmit(count+48);
			PORTA = 0x01;
			_delay_ms(4000);
			PORTA = 0x04;*/
			/*for(b=0;b<count;b++){
				lcd_transmit(CHARACTER);
				for(m=0;m<8;m++){
					tmp =( ((data2[b]&mask[m])>>m)+48);
					lcd_transmit(tmp);
				}
				_delay_ms(3000);
				lcd_transmit(CONTROL);
				lcd_transmit(0x65);
				lcd_transmit(CONTROL);
				lcd_transmit(0x61);
			}
			while(1) PORTA = 0x07;*/
			int y;
			PORTA = 0x03;
			while((y = obd_receive()) != 'E');
			lcd_transmit(y);
			PORTA = 0x04;
			do{
				int n;
				x = obd_receive();
				
				lcd_transmit(x);
			}while(x!=0x3E);


			obd_transmit('A');
			obd_transmit('T');
			obd_transmit('S');
			obd_transmit('P');
			obd_transmit('0');
			obd_transmit(0x0D);
			do{
				x = obd_receive();
				lcd_transmit(x);
			}while(x!=0x3E);
			PORTA = 0x06;
			_delay_ms(1000);

			obd_transmit('A');
			obd_transmit('T');
			obd_transmit('R');
			obd_transmit('V');
			obd_transmit(0x0D);
			do{
				x=obd_receive();
				lcd_transmit(x);
			}while(x!=0x3E);

			//x = obd_receive();
			//PORTA = 0x02;
			//lcd_transmit(CHARACTER);
			//lcd_transmit(x);
			//x = obd_receive();
			//lcd_transmit(CHARACTER);
			//lcd_transmit(x);
			//PORTA = 0x03;
			//PORTA = 0x07;
			//_delay_ms(20);
			PORTA = 0x07;
						
			//while(1){}
			while(1){
				char buffer2[20];
				obd_transmit('0');
				obd_transmit('1');
				obd_transmit('0');
				obd_transmit('0');
				obd_transmit(0x0D);
				
				PORTA = 0x05;
				
				while( (y=obd_receive()) != 0x3E){
					lcd_transmit(y);
				}
				_delay_ms(1000);
				obd_transmit('0');
				obd_transmit('1');
				obd_transmit('0');
				obd_transmit('5');
				obd_transmit(0x0D);
				lcd_transmit('C');
				lcd_transmit('O');
				lcd_transmit('O');
				lcd_transmit('L');
				lcd_transmit('A');
				lcd_transmit('N');
				lcd_transmit('T');
				lcd_transmit(':');
				lcd_transmit(' ');
				while( (y=obd_receive()) != 0x3E){
					lcd_transmit(y);
				}
				lcd_transmit('C');
			}
			/*buffer2[0] = obd_receive();
			obd_transmit(0x00);
			buffer2[1] = obd_receive();
			obd_transmit(0x0D);
			buffer2[2] = obd_receive();
			lcd_transmit(buffer2[2]);
			buffer2[3] = obd_receive();
			lcd_transmit(buffer2[3]);
			buffer2[4] = obd_receive();
			lcd_transmit(buffer2[4]);
			buffer2[5] = obd_receive();
			lcd_transmit(buffer2[5]);
			buffer2[6] = obd_receive();
			lcd_transmit(buffer2[6]);
			buffer2[7] = obd_receive();
			lcd_transmit(buffer2[7]);
			buffer2[8] = obd_receive();
			lcd_transmit(buffer2[8]); 
			buffer2[9] = obd_receive();
			lcd_transmit(buffer2[9]);*/
			
			int m;
			int count3 = 0;
			/*while(count3 != 11){
				lcd_transmit(count3+48);
				lcd_transmit(' ');
				for(m=0;m<8;m++){
					int tmp = (((buffer2[count3] & mask[m]) >> m) +48);
					lcd_transmit(tmp);
				}
				count3++;
				lcd_transmit(0x3E);
			}*/
			
			_delay_ms(1000);	
			/*PORTA = 0x03;
			int v = 0;
			char buffer1[20];
			
			while( (buffer1[v] = obd_receive()) != '3E'){
				lcd_transmit(buffer1[v]);
				v++;
			}
			int g;
			lcd_transmit(v+42);
			for(g=0;g<v;g++){
				lcd_transmit(buffer1[g]);
			}*/


			/*while(1){
				PORTA = 0x01;
				obd_transmit(0x01);
				obd_transmit(0x05);
				obd_transmit(0x0D);
				//if ( obd_receive() == 0x41) PORTA |= 0x01;
				//if ( obd_receive() == 0x05) PORTA |= 0x02;
				lcd_transmit(obd_receive());	
				//lcd_transmit(obd_receive());
				//lcd_transmit(obd_receive());lcd_transmit(obd_receive());
				lcd_transmit(obd_receive());
				lcd_transmit(obd_receive());
				PORTA = 0x07;
				_delay_ms(1000);
			}*/
				
	//	}
//	}
}	 
}

void serial_init(){

//	PRR0 |= (0<<PRUSART1)|(0<<PRUSART0); // Power Reduction Off

	UCSR0A |= (1<<U2X0);
	UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
	UCSR0C |= (0<<USBS0)|(3<<UCSZ00);
	UBRR0H = 0;
	UBRR0L = 12;


	UCSR1A |= (1<<U2X1);
	UCSR1B |= (1<<RXEN1)|(1<<TXEN1); // Allow transmit and receive
	UCSR1C |= (1<<USBS1)|(3<<UCSZ10); // 8 Bit 2 Stop Bits
	UBRR1H = 0;
	UBRR1L = 12; // 9600 Baud
}
void print_lcd (char buffer[]){

/*
 * *       Purpose: Prints string of characters to the LCD
 * *       Input: String of characters desired
 * *       Output: Nothing
 * */

        int i;
        for(i=0;i<sizeof(buffer);i++){
		lcd_transmit(CHARACTER);
                lcd_transmit(buffer[i]);
        }
        return;
}


void lcd_transmit (unsigned char data){
	while( !(UCSR1A & (1<<UDRE1)));
	UDR1 = data;
}

unsigned char lcd_receive (void){
	while (!(UCSR1A & (1<<RXC1)));
	return UDR1;
}	

void obd_transmit (unsigned char data){
	while( !(UCSR0A & (1<<UDRE0)));
	UDR0 = data;
}

unsigned char obd_receive (void){
	while (!(UCSR0A & (1<<RXC0)));
	return UDR0;
}

void lcd_flush (void){
	char tmp;
	while (UCSR1A & (1<<RXC1) ) tmp = UDR1;
}
